package counter.com.baomidou.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import counter.com.baomidou.entity.*;
import counter.com.baomidou.service.ILoudongbuginfoService;
import counter.com.baomidou.service.ILoudongscaninfoService;
import counter.com.baomidou.service.ILoudongtargetinfoService;
import counter.com.common.Result;
import counter.com.connproperty.loudongjiance.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author jobob
 * @since 2020-10-07
 */
@RestController
@RequestMapping("/loudongtargetinfo")
public class LoudongtargetinfoController {

    @Autowired
    ILoudongtargetinfoService targetService;

    @Autowired
    ILoudongbuginfoService bugService;

    @Autowired
    ILoudongscaninfoService scanService;

    @PostMapping("/search")
    public Result search(@RequestBody TargetSearchProperty data) {
        LambdaQueryWrapper<Loudongtargetinfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(true, Loudongtargetinfo::getId);
        Page<Loudongtargetinfo> page = new Page<>(data.getPage(), data.getPagesize());
        IPage<Loudongtargetinfo> iPage = targetService.page(page, wrapper);
        List<Loudongtargetinfo> records = iPage.getRecords();
        List<TargetSearchBag> list = convertSearchRecords(records);
        TargetSearchRespProperty property = new TargetSearchRespProperty();
        property.setList(list);
        property.setTotal(iPage.getTotal());
        return Result.success(property);
    }

    private List<TargetSearchBag> convertSearchRecords(List<Loudongtargetinfo> records) {
        List<TargetSearchBag> bagList = new LinkedList<>();
        for (Loudongtargetinfo info : records) {
            TargetSearchBag bag = new TargetSearchBag();
            Integer targetId = info.getId();
            LambdaQueryWrapper<Loudongbuginfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Loudongbuginfo::getTid, targetId);
            wrapper.eq(Loudongbuginfo::getLevel, LoudongbuginfoController.LEVEL_HIGH);
            int highLevelCount = bugService.count(wrapper);
            wrapper.clear();
            wrapper.eq(Loudongbuginfo::getTid, targetId);
            wrapper.eq(Loudongbuginfo::getLevel, LoudongbuginfoController.LEVEL_MEDIUM);
            int mediumLevelCount = bugService.count(wrapper);
            bag.setHighLevel(highLevelCount);
            bag.setMediumLevel(mediumLevelCount);
            bag.setNote(info.getNote());
            bag.setUrl(info.getUrl());
            bag.setId(info.getId());
            bagList.add(bag);
        }
        return bagList;
    }

    @PostMapping("/search2")
    public Result search2(@RequestBody TargetSearchProperty data) {
        Page<Loudongtargetinfo> page = new Page<>(data.getPage(), data.getPagesize());
        IPage<Loudongtargetinfo> iPage = targetService.page(page);
        List<Loudongtargetinfo> records = iPage.getRecords();
        List<TargetSearch2Bag> list = convertSearch2Records(records);
        TargetSearch2RespProperty property = new TargetSearch2RespProperty();
        property.setTotal(iPage.getTotal());
        property.setList(list);
        return Result.success(property);
    }

    private List<TargetSearch2Bag> convertSearch2Records(List<Loudongtargetinfo> records) {
        List<TargetSearch2Bag> bags = new LinkedList<>();
        for (Loudongtargetinfo info : records) {
            TargetSearch2Bag bag = new TargetSearch2Bag();
            Integer targetId = info.getId();
            Loudongtargetinfo target = targetService.getById(targetId);
            if (target == null) {
                continue;
            }
            LambdaQueryWrapper<Loudongscaninfo> scanWrapper = new LambdaQueryWrapper<>();
            scanWrapper.eq(Loudongscaninfo::getTid, targetId);
            List<Loudongscaninfo> scanList = scanService.list(scanWrapper);
            if (scanList.size() == 0) {
                bag.setStatustime(null);
            } else {
                LocalDateTime latestTime = getLatestTimeFromScanList(scanList);
                bag.setStatustime(latestTime);
            }
            LambdaQueryWrapper<Loudongbuginfo> bugWrapper = new LambdaQueryWrapper<>();
            bugWrapper.eq(Loudongbuginfo::getTid, targetId).eq(Loudongbuginfo::getLevel, LoudongbuginfoController.LEVEL_IGNORE);
            int ignore_count = bugService.count(bugWrapper);
            bugWrapper.clear();
            bugWrapper.eq(Loudongbuginfo::getTid, targetId).eq(Loudongbuginfo::getLevel, LoudongbuginfoController.LEVEL_LOW);
            int low_count = bugService.count(bugWrapper);
            bugWrapper.clear();
            bugWrapper.eq(Loudongbuginfo::getTid, targetId).eq(Loudongbuginfo::getLevel, LoudongbuginfoController.LEVEL_MEDIUM);
            int medium_count = bugService.count(bugWrapper);
            bugWrapper.clear();
            bugWrapper.eq(Loudongbuginfo::getTid, targetId).eq(Loudongbuginfo::getLevel, LoudongbuginfoController.LEVEL_HIGH);
            int high_count = bugService.count(bugWrapper);
            bag.setHolenum_ignore(ignore_count);
            bag.setHolenum_low(low_count);
            bag.setHolenum_medium(medium_count);
            bag.setHolenum_high(high_count);
            bag.setId(info.getId());
            bag.setNote(info.getNote());
            bag.setUrl(info.getUrl());
            bags.add(bag);
        }
        return bags;
    }

    private LocalDateTime getLatestTimeFromScanList(List<Loudongscaninfo> scanList) {
        LocalDateTime latesttime = scanList.get(0).getCreatedtime();
        for (Loudongscaninfo info : scanList) {
            if (info.getCreatedtime().isAfter(latesttime)) {
                latesttime = info.getCreatedtime();
            }
        }
        return latesttime;
    }

    @PostMapping("/add")
    public Result add(@RequestBody @Validated TargetAddProperty data) {
        Loudongtargetinfo info = new Loudongtargetinfo();
        LambdaQueryWrapper<Loudongtargetinfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Loudongtargetinfo::getUrl, data.getUrl());
        Loudongtargetinfo one = targetService.getOne(wrapper);
        if (one != null) {
            return Result.fail("目标已经重复存在");
        }
        info.setUrl(data.getUrl());
        info.setNote(data.getNote());
        generateTargetInitialInfomation(info);
        if (targetService.save(info)) {
            return Result.success("添加成功");
        } else {
            return Result.fail("添加失败");
        }
    }

    /**
     * 生成一些初始化的目标信息
     */
    private void generateTargetInitialInfomation(Loudongtargetinfo info) {
        info.setKeylevel(1);
        info.setSpeed(1);
        info.setContain(false);
        //登陆模块数据
        info.setLoginname("test");
        info.setLoginpassword("test");
        //爬虫导航数据
        info.setUseragent("Mozilla/5.0");
        info.setUseragenttype("Opera");
        info.setSensitivepath("自动");
        info.setOnlycatch(false);
        info.setExclusivepath("/");
        //导入文件模块
        info.setImportfilepath("/");
        //http身份验证
        info.setHttpname("test");
        info.setHttppassword("test");
        //Client Certificate
        info.setCertificatename("四川测试");
        info.setCertificatepassword("test");
        //代理服务器
        info.setProtocolname("HTTP");
        info.setProtocolip("192.168.0.1");
        info.setProtocolport("2000");
        //技术
        info.setTechnologies("[]");
        info.setCustomhttpheaders("[]");
        info.setCustomcookies("[]");
    }

    @PostMapping("/delete")
    public Result delete(@RequestBody TargetDeleteProperty data) {
        if (targetService.removeByIds(Arrays.asList(data.getIds()))) {
            return Result.success("删除成功");
        } else {
            return Result.fail("删除失败");
        }
    }

    @PostMapping("/statistics")
    public Result statistics() {
        LambdaQueryWrapper<Loudongtargetinfo> wrapper = new LambdaQueryWrapper<>();
        int totalCount = targetService.count();
        return Result.success(new TargetStatisticsProperty(totalCount));
    }

    @PostMapping("/detail")
    public Result detail(@RequestBody TargetDetailProperty data) {
        Loudongtargetinfo target = targetService.getById(data.getId());
        if (target == null) {
            return Result.fail("未找到target");
        }
        return Result.success(target);
    }

    @PostMapping("/update")
    public Result update(@RequestBody TargetUpdateProperty data) {
        Loudongtargetinfo target = targetService.getById(data.getId());
        //设置信息
        target.setUrl(data.getUrl());
        target.setKeylevel(data.getKeylevel());
        target.setContain(data.getContain());
        target.setSpeed(data.getSpeed());
        target.setNote(data.getNote());
        //登陆信息
        target.setLoginname(data.getLoginname());
        target.setLoginpassword(data.getLoginpassword());
        //高级设置
        target.setCustomcookies(data.getCustomcookies());
        target.setCustomhttpheaders(data.getCustomhttpheaders());
        target.setTechnologies(data.getTechnologies());
        //验证信息
        target.setCertificatename(data.getCertificatename());
        target.setCertificatepassword(data.getCertificatepassword());
        target.setExclusivepath(data.getExclusivepath());
        //http相关信息
        target.setHttpname(data.getHttpname());
        target.setHttppassword(data.getHttppassword());
        //路径相关信息
        target.setImportfilepath(data.getImportfilepath());
        target.setSensitivepath(data.getSensitivepath());
        target.setOnlycatch(data.getOnlycatch());
        //协议信息
        target.setProtocolname(data.getProtocolname());
        target.setProtocolip(data.getProtocolip());
        target.setProtocolport(data.getProtocolport());
        //用户头信息
        target.setUseragent(data.getUseragent());
        target.setUseragenttype(data.getUseragenttype());
        if (targetService.updateById(target)) {
            return Result.success("添加成功");
        } else {
            return Result.fail("添加失败");
        }
    }
}
